﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Com.Binaria.Core;
using Com.Binaria.Core.Enumeracion;
using Com.Binaria.Core.Exceptions;
using Com.Binaria.SISCOB.DTO;
using Com.Binaria.SISCOB.Dom;
using Com.Binaria.SISCOB.Funcional.DTO;
using Com.Binaria.Core.Util;

namespace Com.Binaria.SISCOB.Mgr
{

    public class ConciliacionMgr : IConciliacionMgr
    {
        #region ATRIBUTOS A EXPONER AL USUARIO
        public IConciliacionDom iConciliacionDom;
        public IItemConceptoDom iItemConceptoDom;
        public IDocumentoTransaccionDom iDocumentoTransaccionDom;
        public ICuentaCorrienteMgr iCuentaCorrienteMgr;
        public IConstante iConstante;

        #endregion

        #region Miembros de IConciliacionMgr
        public ConciliacionFuncionalDTO GetById(ContextoDTO oContexto, System.Int32? Id)
        {
            ConciliacionFuncionalDTO oItem = null;
            //
            try
            {
                ConciliacionDTO tmp = iConciliacionDom.BuscarConciliacionPorId(oContexto, Id);
                if (tmp != null)
                {
                    oItem = new ConciliacionFuncionalDTO();
                    oItem.Id = tmp.Id;
                    oItem.CuentaCorriente = Convert.ToInt32(tmp.IdCuentaCorriente);
                    oItem.CuentaCorrienteFDTO = iCuentaCorrienteMgr.GetById(oContexto, tmp.IdCuentaCorriente);
                    oItem.SaldoMayor = Convert.ToInt64(tmp.SaldoMayor);
                    oItem.SaldoCuenta = Convert.ToInt64(tmp.SaldoCuenta);
                    oItem.FchDesde = tmp.FchDesde;
                    oItem.FchHasta = tmp.FchHasta;
                    oItem.FchCreacion = tmp.FchCreacion;
                    oItem.Obs = tmp.Obs;
                    oItem.EstaCerrada = tmp.EstaCerrada.Value;
                    oItem.UserName = tmp.UserName;
                    //Relacion : ItemConcepto
                    ItemConceptoDTO oRel1 = new ItemConceptoDTO();
                    oRel1.IdConciliacion = Id;

                    IList<ItemConceptoDTO> oRel1s = iItemConceptoDom.BuscarItemConceptoFiltro(oContexto, oRel1);
                    if (oRel1s != null && oRel1s.Count > 0) 
                    {
                        oItem.ItemConcepto = new List<ItemConceptoFuncionalDTO>(oRel1s.Count);
                        for (int i = 0; i < oRel1s.Count; i++) 
                        {
                            ItemConceptoFuncionalDTO oDet = new ItemConceptoFuncionalDTO();
                            oDet.Id = oRel1s[i].Id;
                            oDet.DocumentoTransaccion = Convert.ToInt32(oRel1s[i].IdDocumentoTransaccion);
                            oDet.NmrDocumento = oRel1s[i].NmrDocumento;
                            oDet.Monto = Convert.ToInt64(oRel1s[i].Monto);
                            oDet.FchDocumento = oRel1s[i].FchDocumento;
                            oDet.Tipo = oRel1s[i].Tipo;
                            oDet.TipoText = iConstante.getDomains("domTipoConcepto").Where(itm => itm.Clave.Equals(oRel1s[i].Tipo)).First().Valor;
                            oDet.Glosa = oRel1s[i].Glosa;
                            //
                            oItem.ItemConcepto.Add(oDet);
                        }
                    }
                }
            }
            catch (Exception ex) { throw new ManagerException(ex.Message, System.Diagnostics.TraceEventType.Warning); }
            return oItem;
        }

        public IList<ConciliacionFuncionalDTO> GetAll(ContextoDTO oContexto)
        {
            IList<ConciliacionFuncionalDTO> oItem = null;
            //
            try
            {
                IList<ConciliacionDTO> tmp = iConciliacionDom.BuscarConciliacionTodos(oContexto);
                if (tmp != null)
                {
                    oItem = new List<ConciliacionFuncionalDTO>(tmp.Count);
                    for (int i = 0; i < tmp.Count; i++)
                    {
                        ConciliacionFuncionalDTO oFDto = new ConciliacionFuncionalDTO();
                        oFDto.Id = tmp[i].Id;
                        oFDto.CuentaCorriente = Convert.ToInt32(tmp[i].IdCuentaCorriente);
                        oFDto.SaldoMayor = Convert.ToInt64(tmp[i].SaldoMayor);
                        oFDto.SaldoCuenta = Convert.ToInt64(tmp[i].SaldoCuenta);
                        oFDto.FchDesde = tmp[i].FchDesde;
                        oFDto.FchHasta = tmp[i].FchHasta;
                        oFDto.FchCreacion = tmp[i].FchCreacion;
                        oFDto.Obs = tmp[i].Obs;
                        oFDto.EstaCerrada = tmp[i].EstaCerrada.Value;
                        oFDto.UserName = tmp[i].UserName;
                        //
                        oItem.Add(oFDto);
                    }
                }
            }
            catch (Exception ex) { throw new ManagerException(ex.Message, System.Diagnostics.TraceEventType.Warning); }
            return oItem;
        }

        public IList<ConciliacionFuncionalDTO> GetBy(ContextoDTO oContexto, ConciliacionFuncionalDTO item)
        {
            IList<ConciliacionFuncionalDTO> oItem = null;
            //
            try
            {
                IList<ConciliacionDTO> tmp = null;
                if (item == null)
                    tmp = iConciliacionDom.BuscarConciliacionTodos(oContexto);
                else
                {
                    ConciliacionDTO oDto = new ConciliacionDTO();
                    oDto.Id = item.Id;
                    if (item.CuentaCorriente > 0) oDto.IdCuentaCorriente = item.CuentaCorriente;
                    if (item.SaldoMayor > 0) oDto.SaldoMayor = item.SaldoMayor;
                    if (item.SaldoCuenta > 0) oDto.SaldoCuenta = item.SaldoCuenta;
                    oDto.FchDesde = item.FchDesde;
                    oDto.FchHasta = item.FchHasta;
                    oDto.FchCreacion = item.FchCreacion;
                    //
                    tmp = iConciliacionDom.BuscarConciliacionFiltro(oContexto, oDto);
                }

                if (tmp != null)
                {
                    oItem = new List<ConciliacionFuncionalDTO>(tmp.Count);
                    for (int i = 0; i < tmp.Count; i++)
                    {
                        ConciliacionFuncionalDTO oFDto = new ConciliacionFuncionalDTO();
                        oFDto.Id = tmp[i].Id;
                        oFDto.CuentaCorriente = Convert.ToInt32(tmp[i].IdCuentaCorriente);
                        oFDto.SaldoMayor = Convert.ToInt64(tmp[i].SaldoMayor);
                        oFDto.SaldoCuenta = Convert.ToInt64(tmp[i].SaldoCuenta);
                        oFDto.FchDesde = tmp[i].FchDesde;
                        oFDto.FchHasta = tmp[i].FchHasta;
                        oFDto.FchCreacion = tmp[i].FchCreacion;
                        oFDto.Obs = tmp[i].Obs;
                        oFDto.EstaCerrada = tmp[i].EstaCerrada.Value;
                        oFDto.UserName = tmp[i].UserName;
                        //
                        oItem.Add(oFDto);
                    }
                }
            }
            catch (Exception ex) { throw new ManagerException(ex.Message, System.Diagnostics.TraceEventType.Warning); }
            return oItem;
        }

        [Binaria.Core.Attribute.Trasanction(System.Transactions.TransactionScopeOption.Required)]
        public bool Save(ContextoDTO oContexto, ConciliacionFuncionalDTO item)
        {
            bool IsOK = false;
            bool IsExist = (item.Id.HasValue && item.Id > 0);
            List<int> oUpd = null;

            ItemConceptoFuncionalDTO itemConcFDTO = null;
            IList<DocumentoTransaccionDTO> listaEgreso = null;
            IList<DocumentoTransaccionDTO> listaIngreso = null;

            try
            {

                ConciliacionDTO oDto = new ConciliacionDTO();
                oDto.Id = item.Id;
                oDto.IdCuentaCorriente = item.CuentaCorriente;
                oDto.SaldoMayor = item.SaldoMayor;
                oDto.SaldoCuenta = item.SaldoCuenta;
                oDto.FchDesde = item.FchDesde;
                oDto.FchHasta = item.FchHasta;
                oDto.FchCreacion = item.FchCreacion;
                oDto.Obs = item.Obs;
                oDto.EstaCerrada = item.EstaCerrada;
                oDto.UserName = item.UserName;

                listaEgreso = iDocumentoTransaccionDom.BuscarEgresoObservado(oContexto, oDto);
                listaIngreso = iDocumentoTransaccionDom.BuscarIngresoObservado(oContexto, oDto);

                item.ItemConcepto = new List<ItemConceptoFuncionalDTO>();
                foreach (DocumentoTransaccionDTO docTransDTO in listaIngreso)
                {

                    itemConcFDTO = new ItemConceptoFuncionalDTO()
                    {
                        DocumentoTransaccion = docTransDTO.Id.Value,
                        FchDocumento = docTransDTO.FchDocumento,
                        Glosa = docTransDTO.Glosa,
                        Monto = docTransDTO.Monto.Value,
                        NmrDocumento = docTransDTO.NmrDocumento,
                    };

                    if (docTransDTO.Estado.Equals("OB"))
                    {
                        itemConcFDTO.Tipo = "3";
                    }

                    if (docTransDTO.Estado.Equals("RE"))
                    {
                        itemConcFDTO.Tipo = "5";
                    }


                    item.ItemConcepto.Add(itemConcFDTO);
                }

                foreach (DocumentoTransaccionDTO docTransDTO in listaEgreso)
                {

                    itemConcFDTO = new ItemConceptoFuncionalDTO()
                    {
                        DocumentoTransaccion = docTransDTO.Id.Value,
                        FchDocumento = docTransDTO.FchDocumento,
                        Glosa = docTransDTO.Glosa,
                        Monto = docTransDTO.Monto.Value,
                        NmrDocumento = docTransDTO.NmrDocumento,
                    };

                    if (docTransDTO.Estado.Equals("GI"))
                    {
                        itemConcFDTO.Tipo = "2";
                    }
                    if (docTransDTO.Estado.Equals("ON"))
                    {
                        itemConcFDTO.Tipo = "1";
                    }
                    if (docTransDTO.Estado.Equals("OI"))
                    {
                        itemConcFDTO.Tipo = "4";
                    }

                    item.ItemConcepto.Add(itemConcFDTO);
                }

                if (IsExist)
                    iConciliacionDom.RegistrarConciliacion(oContexto, new List<ConciliacionDTO>() { oDto }, EnumRegistrarAccion.Modificar);
                else
                    iConciliacionDom.RegistrarConciliacion(oContexto, new List<ConciliacionDTO>() { oDto }, EnumRegistrarAccion.Agregar);

                //Relacion MD18: ItemConcepto
                oUpd = null;
                if (IsExist)
                {
                    ItemConceptoDTO oRel1 = new ItemConceptoDTO();
                    oRel1.IdConciliacion = oDto.Id;
                    List<ItemConceptoDTO> oRel1s = iItemConceptoDom.BuscarItemConceptoFiltro(oContexto, oRel1);
                    if (oRel1s != null && oRel1s.Count > 0)
                    {
                        //UPD - DEL
                        if (item.ItemConcepto != null)
                        {
                            oUpd = item.ItemConcepto.Join(oRel1s
                                    , ori => ori.Id
                                    , des => des.Id
                                    , (ori, des) => (int)des.Id).ToList();
        
                            oRel1s = oRel1s.Where(ori => !item.ItemConcepto.Any(des => des.Id == ori.Id)).ToList();
                        }
                    }
                    iItemConceptoDom.RegistrarItemConcepto(oContexto, oRel1s, EnumRegistrarAccion.Eliminar);
                }
                
                if (item.ItemConcepto != null) 
                {
                    for (int i = 0; i < item.ItemConcepto.Count; i++) 
                    {
                        ItemConceptoDTO oRel1 = new ItemConceptoDTO();
                        oRel1.IdConciliacion = oDto.Id;                        
                        oRel1.Id = item.ItemConcepto[i].Id;
                        bool esta_ = (oUpd != null && oRel1.Id.HasValue && oUpd.Contains((int)oRel1.Id));
                        //
                        oRel1.IdDocumentoTransaccion = item.ItemConcepto[i].DocumentoTransaccion;
                        oRel1.NmrDocumento = item.ItemConcepto[i].NmrDocumento;
                        oRel1.Monto = item.ItemConcepto[i].Monto;
                        oRel1.FchDocumento = item.ItemConcepto[i].FchDocumento;
                        oRel1.Tipo = item.ItemConcepto[i].Tipo;
                        oRel1.Glosa = item.ItemConcepto[i].Glosa;
                        //
                        iItemConceptoDom.RegistrarItemConcepto(oContexto, new List<ItemConceptoDTO>() { oRel1 }, esta_ ? EnumRegistrarAccion.Modificar : EnumRegistrarAccion.Agregar);
                    }
                }
                IsOK = true;
            }
            catch (Exception ex) { throw new ManagerException(ex.Message, System.Diagnostics.TraceEventType.Warning); }
            return IsOK;
        }

        [Binaria.Core.Attribute.Trasanction(System.Transactions.TransactionScopeOption.Required)]
        public bool Delete(ContextoDTO oContexto, ConciliacionFuncionalDTO item)
        {
            bool IsOK = false;
            bool IsExist = (item.Id.HasValue && item.Id > 0);

            try
            {
                ConciliacionDTO oDto = new ConciliacionDTO();
                oDto.Id = item.Id;
                
                if (IsExist)
                {
                    //Relacion :  ItemConcepto
                    ItemConceptoDTO oRel1 = new ItemConceptoDTO();
                    oRel1.Id = item.Id;
                    List<ItemConceptoDTO> oRel1s = iItemConceptoDom.BuscarItemConceptoFiltro(oContexto, oRel1);
                    if (oRel1s != null && oRel1s.Count > 0)
                    {
                        iItemConceptoDom.RegistrarItemConcepto(oContexto, oRel1s, EnumRegistrarAccion.Eliminar);
                    }
                    iConciliacionDom.RegistrarConciliacion(oContexto, new List<ConciliacionDTO>() { oDto }, EnumRegistrarAccion.Eliminar);
                }
                IsOK = true;
            }
            catch (Exception ex) { throw new ManagerException(ex.Message, System.Diagnostics.TraceEventType.Warning); }
            return IsOK;
        }
        #endregion


        public ReporteConciliacionFuncionalDTO PrepararConciliacion(ContextoDTO oContexto, int p_IdConcFDTO)
        {
            ConciliacionFuncionalDTO concFDTO = null;
            ReporteConciliacionFuncionalDTO rptConcFDTO = new ReporteConciliacionFuncionalDTO();

            long TotDetalleChequesNoCobrados = 0;
            long TotDetalleChequesNoContabilizados = 0;
            long TotDetalleChequesConObservacion = 0;
            long TotDetalleIngresosNoContabilizados = 0;
            long TotDetalleIngresosNoAbonados = 0;
            long ValidDif = 0;

            IList<ItemConceptoFuncionalDTO> _DetalleChequesNoCobrados = new List<ItemConceptoFuncionalDTO>();
            IList<ItemConceptoFuncionalDTO> _DetalleChequesNoContabilizados = new List<ItemConceptoFuncionalDTO>();
            IList<ItemConceptoFuncionalDTO> _DetalleChequesConObservacion = new List<ItemConceptoFuncionalDTO>();
            IList<ItemConceptoFuncionalDTO> _DetalleIngresosNoContabilizados = new List<ItemConceptoFuncionalDTO>();
            IList<ItemConceptoFuncionalDTO> _DetalleIngresosNoAbonados = new List<ItemConceptoFuncionalDTO>();

            //
            try
            {
                concFDTO = this.GetById(oContexto, p_IdConcFDTO);


                if (concFDTO != null)
                {
                    rptConcFDTO.TituloReporte = "Informe de Conciliación Bancaria SEREMI de Salud";
                    rptConcFDTO.NumeroDeCuenta = concFDTO.CuentaCorrienteFDTO.NmrCuenta;
                    rptConcFDTO.FechaEmision = concFDTO.FchCreacionText;
                    rptConcFDTO.FechaInicioPeriodo = concFDTO.FchDesdeText;
                    rptConcFDTO.FechaFinPeriodo = concFDTO.FchHastaText;

                    rptConcFDTO.TotalSaldoLibroMayor = concFDTO.SaldoMayor.ToString();
                    rptConcFDTO.TotalSaldoCuentaCorriente = concFDTO.SaldoCuenta.ToString();

                    rptConcFDTO.GlosaFirmaIzquierda = iConstante.getValue("FirmaIzquierda");
                    rptConcFDTO.GlosaFirmaCentro = iConstante.getValue("FirmaCentro");
                    rptConcFDTO.GlosaFirmaDerecha = iConstante.getValue("FirmaDerecha");

                    ValidDif += concFDTO.SaldoMayor;
                    foreach (ItemConceptoFuncionalDTO itemConcFDTO in concFDTO.ItemConcepto)
                    {

                        if (itemConcFDTO.Tipo.Equals("1"))
                        {
                            _DetalleChequesNoContabilizados.Add(itemConcFDTO);
                            TotDetalleChequesNoContabilizados += (itemConcFDTO.Monto * -1);
                        }
                        if (itemConcFDTO.Tipo.Equals("2"))
                        {
                            _DetalleChequesNoCobrados.Add(itemConcFDTO);
                            TotDetalleChequesNoCobrados += (itemConcFDTO.Monto * 1);
                        }
                        if (itemConcFDTO.Tipo.Equals("3"))
                        {
                            _DetalleIngresosNoContabilizados.Add(itemConcFDTO);
                            TotDetalleIngresosNoContabilizados += (itemConcFDTO.Monto * 1);
                        }
                        if (itemConcFDTO.Tipo.Equals("4"))
                        {
                            _DetalleChequesConObservacion.Add(itemConcFDTO);
                            TotDetalleChequesConObservacion += (itemConcFDTO.Monto * -1);
                        }

                        if (itemConcFDTO.Tipo.Equals("5"))
                        {
                            _DetalleIngresosNoAbonados.Add(itemConcFDTO);
                            TotDetalleIngresosNoAbonados += (itemConcFDTO.Monto * -1);
                        }
                    }
                    ValidDif += TotDetalleChequesNoContabilizados;
                    ValidDif += TotDetalleChequesNoCobrados;
                    ValidDif += TotDetalleIngresosNoContabilizados;
                    ValidDif += TotDetalleChequesConObservacion;
                    ValidDif += TotDetalleIngresosNoAbonados;

                    ValidDif = ValidDif - concFDTO.SaldoCuenta;
                    rptConcFDTO.Observaciones = string.Format(concFDTO.Obs + " Diferencia : {0}",ValidDif.ToString());

                    rptConcFDTO.TotalChequesNoCobrados = TotDetalleChequesNoCobrados.ToString();
                    rptConcFDTO.TotalChequesNoContabilizados = TotDetalleChequesNoContabilizados.ToString();
                    rptConcFDTO.TotalChequesConObservacion = TotDetalleChequesConObservacion.ToString();
                    rptConcFDTO.TotalIngresosNoContabilizados = TotDetalleIngresosNoContabilizados.ToString();
                    rptConcFDTO.TotalIngresosNoAbonados = TotDetalleIngresosNoAbonados.ToString();

                    rptConcFDTO.DetalleMovimientosConciliacion.Add("Detalle Cheques No Cobrados", _DetalleChequesNoCobrados);
                    rptConcFDTO.DetalleMovimientosConciliacion.Add("Detalle Cheques No Contabilizados", _DetalleChequesNoContabilizados);
                    rptConcFDTO.DetalleMovimientosConciliacion.Add("Detalle Cheques Con Observacion", _DetalleChequesConObservacion);
                    rptConcFDTO.DetalleMovimientosConciliacion.Add("Detalle Ingresos No Contabilizados", _DetalleIngresosNoContabilizados);
                    rptConcFDTO.DetalleMovimientosConciliacion.Add("Detalle Ingresos No Abonados", _DetalleIngresosNoAbonados);

                }
            }
            catch (Exception ex) { throw new ManagerException(ex.Message, System.Diagnostics.TraceEventType.Warning); }
            return rptConcFDTO;
        }

    }
}
